﻿#include<iostream>

#include <gp_Pnt.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepPrimAPI_MakePrism.hxx>
#include <BRepCheck_Analyzer.hxx>

#include "OCCTModel.h"

using namespace std;

OCCTModel::OCCTModel()
{
}

OCCTModel::~OCCTModel()
{
}

OCCTModel &OCCTModel::getInstance()
{
    // 局部静态特性的方式实现单例
    // c++11后，此方法不存在线程不安全问题
    static OCCTModel instance;
    return instance;
}

TopoDS_Shape OCCTModel::DoModel()
{
    if(!m_Data) return TopoDS_Shape();

    TopoDS_Shape result;

    if(abs(m_Data->m_Thickness - 0) > 1e-6)
        result = DoModel3d(); // 3D建模
    else 
        result = DoModel2d(); // 2D建模

    // 模型检查
    BRepCheck_Analyzer analyzer(result);
    if (!analyzer.IsValid()) 
        std::cerr << "OCCTModel::DoModel() There is a topology error in the model!" << std::endl;
        
    return result;
}

TopoDS_Shape OCCTModel::DoModel2d()
{
    BRepBuilderAPI_MakeWire wire;
    for (size_t i = 0; i < m_Data->m_Vertices.size(); i++)
    {
        const auto& x1 = m_Data->m_Vertices[i];
        gp_Pnt p1(x1[0], x1[1], x1[2]);
        gp_Pnt p2;
        if(i + 1 == m_Data->m_Vertices.size())
        {
            const auto& x2 = m_Data->m_Vertices[0];
            p2.SetCoord(x2[0], x2[1], x2[2]);
        }
        else
        {
            const auto& x2 = m_Data->m_Vertices[i + 1];
            p2.SetCoord(x2[0], x2[1], x2[2]);
        }
        
        BRepBuilderAPI_MakeEdge edge(p1, p2);
        wire.Add(edge.Edge());
    }

    BRepBuilderAPI_MakeFace face(wire.Wire());
    return face.Shape();
}

TopoDS_Shape OCCTModel::DoModel3d()
{
    const auto& dir = m_Data->m_Direct;
    return BRepPrimAPI_MakePrism(DoModel2d(), gp_Vec(dir[0], dir[1], dir[2]));
}